/*
 * server.c
 *
 *  Created on: 28/10/2011
 *      Author: Normandia
 */

#include "cliente.h"

int conectarClientes(uint8_t cant_conexiones){

	//struct Parametros parametros; //estructura que carga los parametros del archivo de configuracion
	struct sockaddr_in ftpAddr;

	uint8_t i;
	
	clients = malloc(sizeof(struct sockaddr_in) * cant_conexiones);
	cliente_libre = malloc(sizeof(uint8_t) * cant_conexiones);
	//semaforo_cliente = malloc(sizeof(sem_t) * cant_conexiones);
	//buffer_cliente = malloc(sizeof(T_MENSAJE) * cant_conexiones);
	num_clients = 1;

	if(sem_init(&socket_ready, 0, 0) == -1) {
		//logERROR("HTTP SERVER","Error en listen");
		return 0;
	}

	if(sem_init(&mutex_busqueda,0,1) == -1){
		//logERROR("HTTP SERVER","Error en listen");
		return 0;
	}

	// Conecta el primer socket y hace handshake
	if ((clients[0] = mksocket(CLIENT, configuracion.Addr, configuracion.port, &ftpAddr)) < 0) {
			close(clients[0]);
			printf("No conectó\n");
			exit(0);
	}

	sem_post(&socket_ready);
	cliente_libre[0] = LIBRE;

	printf("Haciendo handshake\n");
	if(!handShake()){
		printf("Se cerror la conexion\n");
		exit(0);
	}
	/*{
		do{
			printf("Intento handshake\n");
			/*close(clients[0]);
			if ((clients[0] = mksocket(CLIENT, configuracion.Addr, configuracion.port, &ftpAddr)) < 0) {
					close(clients[0]);
					printf("No conectó\n");
					exit(0);
			}

			if(connect(clients[0],(struct sockaddr *)&ftpAddr,sizeof(struct sockaddr_in)) < 0) {
				perror("connect");
				close(clients[0]);
			}
		}while(!handShake());
	}*/
	printf("Handshake hecho\n");

	for(i=1;i<cant_conexiones;i++){

		if ((clients[i] = mksocket(CLIENT, configuracion.Addr, configuracion.port, &(ftpAddr))) < 0) {
				close(clients[i]);
				printf("No conectó\n");
				exit(0);
		}

		cliente_libre[i] = LIBRE;
		num_clients++;
		sem_post(&socket_ready);

	}

	return 0;
}

T_MENSAJE* enviarYRecibir(T_MENSAJE* mensaje) {

	T_MENSAJE* respuesta;
	uint8_t id_socket;

	id_socket = obtenerSocketReady();
	enviar(id_socket, mensaje);
	respuesta = recibir(id_socket);
	liberarSocket(id_socket);

	return respuesta;

}

void enviar(uint8_t id_socket, T_MENSAJE* mensaje) {

	T_MENSAJE* respuesta;

	if(enviarPorSocket(clients[id_socket],mensaje)) {
		perror("enviarPorSocket");
	}
	eliminarMensaje(mensaje);

}

T_MENSAJE* recibir(uint8_t id_socket) {

	T_MENSAJE* respuesta;

	if(recibirDeSocket(clients[id_socket],&respuesta)) {
		perror("enviarPorSocket");
	}
	return respuesta;

}

uint8_t obtenerSocketReady() {

	uint8_t i;

	sem_wait(&socket_ready);
	sem_wait(&mutex_busqueda);

	for(i=0;i<num_clients;i++) {

		if(cliente_libre[i] == LIBRE){
			cliente_libre[i] = OCUPADO;
			sem_post(&mutex_busqueda);
			return i;
		}

	}

	return -1;

}

void liberarSocket(uint8_t socket_id) {

	cliente_libre[socket_id] = LIBRE;
	sem_post(&socket_ready);

}

int handShake() {

	T_MENSAJE* msj_handshake;
	char acepto = 0;

	msj_handshake = generarMensaje(TIPO_HANDSHAKE,0,NULL);
	msj_handshake = enviarYRecibir(msj_handshake);
	acepto = (msj_handshake->tipo == TIPO_HANDSHAKE && msj_handshake->length == 0);
	eliminarMensaje(msj_handshake);

	return acepto;

}
